package com.lzy.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lzy.annotation.DataScope;
import com.lzy.constant.Constants;
import com.lzy.context.LocalUser;
import com.lzy.dao.*;
import com.lzy.entity.*;
import com.lzy.enums.ExceptionEnums;
import com.lzy.exception.ServiceException;
import com.lzy.exception.user.UserException;
import com.lzy.exception.user.UserPasswordNotMatchException;
import com.lzy.security.LoginUser;
import com.lzy.utils.SecurityUtil;
import com.lzy.utils.ServletUtils;
import com.lzy.utils.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.lzy.service.ISysUserService;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class SysUserService extends ServiceImpl<SysUserDao, SysUserEntity> implements ISysUserService {

    private static final Logger log = LoggerFactory.getLogger(SysUserService.class);

    @Autowired
    private SysUserRoleDao sysUserRoleDao;

    @Autowired
    private SysUserDao mapper;

    @Autowired
    private SysRoleDao sysRoleDao;

    @Autowired
    private SysMenuDao sysMenuDao;

    @Autowired
    private SysUserPostDao sysUserPostDao;

    @Autowired
    private SysDeptDao sysDeptDao;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeUserInfo(List<Long> userIds) {

        // 删除用户与岗位关联
        sysUserPostDao.deleteBatchIds(userIds);
        // 删除用户角色信息
        sysUserRoleDao.deleteBatchIds(userIds);
        // 删除用户
        mapper.deleteBatchIds(userIds);
    }

    @Override
    public LoginUser selectUserInfoById(Long userId) {

        LoginUser loginUser = new LoginUser();
        if (StringUtil.isNull(userId)) {
            throw new ServiceException(ExceptionEnums.BUSINESS_EXCEPTION.getCode(), ExceptionEnums.BUSINESS_EXCEPTION.getMessage());
        }

        // 验证权限
        List<String> roles = LocalUser.getLoginUser().getRoles().stream().filter(item -> Constants.ADMIN.equals(item)).collect(Collectors.toList());
        if (!LocalUser.me().getUserId().equals(userId) && StringUtil.isNull(roles)) {
            throw new ServiceException(ExceptionEnums.NO_PERMISSION_OPERATION.getCode(), ExceptionEnums.NO_PERMISSION_OPERATION.getMessage());
        }

        // get info
        SysUserEntity sysUserEntity = mapper.selectById(userId);
        if (StringUtil.isNull(sysUserEntity)) {
            throw new UserException(ExceptionEnums.USER_NOT_FOUND.getCode(), ExceptionEnums.USER_NOT_FOUND.getMessage());
        }

        // 获取用户角色信息
        List<SysRoleEntity> sysRoleEntities = sysRoleDao.selectRoleByUserIdRoleName(userId);
        loginUser.setUser(sysUserEntity);
        loginUser.setRoles(new HashSet<>(sysRoleEntities.stream().map(item -> item.getRoleKey()).collect(Collectors.toList())));

        // 获取权限信息
        List<String> permissions = mapper.selectUserPermission(userId)
                .stream()
                .filter(item -> !item.equals(" "))
                .collect(Collectors.toList());

        loginUser.setPermissions(new HashSet<>(permissions));
        return loginUser;
    }

    @Override
    public boolean checkUserWhetherExists(String userName) {

        int count = mapper.selectUserByUserName(userName);
        return count > 0;
    }

    @Override
    public boolean checkUserPhoneWhetherExists(String phonenumber) {

        int count = mapper.selectUserByPhoneNumber(phonenumber);
        return count > 0;
    }

    @Override
    public boolean checkUserEmailWhetherExists(String email) {

        int count = mapper.selectUserByEmail(email);
        return count > 0;
    }

    @Override
    public void registerSysUser(SysUserEntity sysUser) {

        if (checkUserWhetherExists(sysUser.getUserName())) {
            throw new ServiceException(ExceptionEnums.USER_ALREADY_EXISTS.getCode(), "当前用户" + sysUser.getUserName() + "已存在！");
        } else if (StringUtil.isEmpty(sysUser.getPhonenumber())
                && checkUserPhoneWhetherExists(sysUser.getPhonenumber())) {
            throw new ServiceException(ExceptionEnums.USER_ALREADY_EXISTS.getCode(), "当前用户" + sysUser.getUserName() + "手机号已存在！");
        } else if (StringUtil.isEmpty(sysUser.getEmail())
                && checkUserEmailWhetherExists(sysUser.getEmail()))
        {
            throw new ServiceException(ExceptionEnums.USER_ALREADY_EXISTS.getCode(), "当前用户" + sysUser.getUserName() + "邮箱已存在！");
        }
        sysUser.setPassword(SecurityUtil.encryptPassword(sysUser.getPassword()));
        sysUser.setCreateTime(new Date());
        sysUser.setCreateBy(LocalUser.me().getUserName());
        mapper.insert(sysUser);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addSysUser(SysUserEntity sysUser) {

        sysUser.setPassword(SecurityUtil.encryptPassword(sysUser.getPassword()));
        // 添加用户
        registerSysUser(sysUser);
        // 添加用户的岗位信息
        inertUserPost(sysUser);
        // 添加用户的角色信息
        insertUserRole(sysUser);
    }

    private void insertUserRole(SysUserEntity sysUser) {

        Set<Long> roleIds = sysUser.getRoles().stream().map(item -> item.getRoleId()).collect(Collectors.toSet());
        if (StringUtil.isNotEmpty(roleIds))
        {
            // 新增用户与岗位管理
            sysUserRoleDao.batchInsert(sysUser.getUserId(), roleIds);
        }
    }

    /**
     * 添加岗位信息
     * @param sysUser 用户
     */
    private void inertUserPost(SysUserEntity sysUser) {

        Set<Long> postIds = sysUser.getPosts().stream().map(item -> item.getPostId()).collect(Collectors.toSet());
        if (StringUtil.isNotEmpty(postIds))
        {
            // 新增用户与岗位管理
            List<SysUserPostEntity> list = new ArrayList<>();
            for (Long postId : postIds)
            {
                SysUserPostEntity up = new SysUserPostEntity();
                up.setUserId(sysUser.getUserId());
                up.setPostId(postId);
                list.add(up);
            }
            sysUserPostDao.batchInsert(list);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUserInfo(SysUserEntity sysUser) {

        if (StringUtil.isEmpty(sysUser.getPhonenumber())
                && checkUserPhoneWhetherExists(sysUser.getPhonenumber())) {
            throw new ServiceException(ExceptionEnums.USER_ALREADY_EXISTS.getCode(), "当前用户" + sysUser.getUserName() + "手机号已存在！");
        } else if (StringUtil.isEmpty(sysUser.getEmail())
                && checkUserEmailWhetherExists(sysUser.getEmail()))
        {
            throw new ServiceException(ExceptionEnums.USER_ALREADY_EXISTS.getCode(), "当前用户" + sysUser.getUserName() + "邮箱已存在！");
        }

        sysUser.setUpdateBy(SecurityUtil.getUsername());
        sysUser.setUpdateTime(new Date());

        // 添加用户角色信息
        sysUserRoleDao.deleteById(sysUser.getUserId());
        insertUserRole(sysUser);

        // 添加用户岗位信息
        sysUserPostDao.deleteById(sysUser.getUserId());
        inertUserPost(sysUser);

        mapper.updateById(sysUser);
    }

    @Override
    public void resetPwd(SysUserEntity user) {

        if (StringUtil.isEmpty(user.getPassword())) {
            user.setPassword(SecurityUtil.encryptPassword("123456"));
        } else {
            user.setPassword(SecurityUtil.encryptPassword(user.getPassword()));
        }
        user.setUpdateBy(SecurityUtil.getUsername());
        mapper.updateUser(user);
    }

    @Override
    public void updateUserStatus(SysUserEntity user) {

        user.setUpdateBy(SecurityUtil.getUsername());
        mapper.updateUser(user);
    }

    @Override
    public List<String> getRolesByUserId(Long userId) {

        return sysRoleDao
                .selectRoleByUserIdRoleName(userId)
                .stream()
                .map(item -> item.getRoleKey())
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertUserAuth(Long userId, Long... roleIds) {

        sysUserRoleDao.delete(Wrappers.<SysUserRoleEntity>lambdaUpdate().eq(SysUserRoleEntity::getUserId, userId));
        sysUserRoleDao.batchInsert(userId, Arrays.stream(roleIds).collect(Collectors.toList()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeUserPwd(String originPwd, String password) {
        SysUserEntity sysUserEntity = mapper.selectById(LocalUser.me().getUserId());
        if (!SecurityUtil.verifyPassword(originPwd, sysUserEntity.getPassword())) {
            throw new UserPasswordNotMatchException(ExceptionEnums.PASSWORD_NOT_MATCH.getCode(), ExceptionEnums.PASSWORD_NOT_MATCH.getMessage());
        }
        mapper.updateUserPwd(LocalUser.me().getUserId(), SecurityUtil.encryptPassword(password));
    }

    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public IPage<Map<String, Object>> selectPageListByConditional(SysUserEntity sysUserEntity) {

        Page<Map<String, Object>> result = new Page<>(sysUserEntity.getPage().getPageNum(), sysUserEntity.getPage().getPageSize());
        IPage<Map<String, Object>> mapIPage = baseMapper.selectPageList(result, sysUserEntity);
        return mapIPage;
    }
}